/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/* 
 * Copyright (c) 2009 City University of Hong Kong
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License m_version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Author: Wilson Thong (wilsonwk@ee.cityu.edu.hk) 
 */
#include "bmsn-routing-manager.h" 
#include "ipv4-deflection-routing.h"

NS_LOG_COMPONENT_DEFINE ("BmsnRoutingManager");

namespace ns3 {
namespace eecityu {

void 
BmsnRoutingManager::PopulateRoutingTables (const BmsnTopology& bmsnNet, bool enableDeflect)
{
  NS_LOG_FUNCTION ( &bmsnNet );

  // Obtain the number of rows in this square BMSN topology
  uint32_t nRows = bmsnNet.GetNRows ();
  // Obtain the set of all nodes of the BMSN topology, and install
  // the BMSN routing protocol to each of the node
  //
  // Obtain the set of all nodes
  const NodeContainer& nodes = bmsnNet.GetNodeContainer ();
  // Walk through all the node and install the BMSN routing protocol
  for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); i++)
  {
      Ptr<Node> node = *i;

      Ptr<BmsnRouting> bmsnRouting = CreateObject<BmsnRouting> ();
      Ptr<Ipv4DeflectionRouting> dfRouting = CreateObject<Ipv4DeflectionRouting> ();
      // initialize the BmsnRouting protocool such that its operation
      // aligns with the BMSN topology with size nRows-by-nRows
      bmsnRouting->SetAttribute ("nRows", UintegerValue (nRows));
      bmsnRouting->SetNode (node);
      NS_LOG_LOGIC ("Adding BmsnRouting Protocol to node " << node->GetId ()
        << " with priority " << bmsnRouting->GetPriority ());
      // This is the object that will calculate BMSN routes.  We insert it
      // at slightly higher priority than GlobalRouting and static routing 
      // (which is at three and zero, respectively).
      // This means that BMSN routes (e.g. host routes) will be consulted
      // before GlobalRoutes and also before static routes
      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
      NS_ASSERT_MSG (ipv4, "An Ipv4 protocool object is not found. Ipv4 protocol "
        << "object is needed in order to access the list of routing protocols "
        << "available to the node. Ipv4 object should be aggregated to the node "
        << "during network topology generation.");
      Ptr<Ipv4ListRouting> ipv4ListRouting = DynamicCast<Ipv4ListRouting> (ipv4->GetRoutingProtocol ());
      NS_ASSERT_MSG (ipv4ListRouting, "Ipv4ListRouting protocol object is "
        << "not found. Ipv4ListRouting protocol object is needed in order to add "
        << "a new routing protocol to the node. Ipv4ListRouting object should be "
        << "aggregated to the node during network topology generation.");
      // add the BmsnRouting object to the node
      ipv4ListRouting->AddRoutingProtocol (bmsnRouting, bmsnRouting->GetPriority ());  
      NS_LOG_LOGIC ("BmsnRouting protocol object added to the node-" << node->GetId () 
        << " with priority " << bmsnRouting->GetPriority ());
      // add the Ipv4DeflectionRouting object to the node
      if (enableDeflect)
      {
        int16_t dfPriority = bmsnRouting->GetPriority () + 50;
        ipv4ListRouting->AddRoutingProtocol (dfRouting, dfPriority); 
        NS_LOG_LOGIC ("Ipv4DeflectionRouting protocol object added to the node-" 
          << node->GetId () << " with priority " << dfPriority);
      }
      else
        NS_LOG_LOGIC ("Deflection routing is disabled on node-" << node->GetId ());
  }
}

} // namespace eecityu
} // namespace ns3
